// @ts-check
import * as THREE from 'three'
import * as CANNON from 'cannon'

class Map {
  constructor({
    world
  }) {
    this._boxes = []
    this._boxMeshes = []
    this._world = world

    const geometry = new THREE.PlaneGeometry(300, 300, 50, 50);
    geometry.applyMatrix(new THREE.Matrix4().makeRotationX(- Math.PI / 2))

    const material = new THREE.MeshLambertMaterial({ color: 0xdddddd })

    const mesh = new THREE.Mesh(geometry, material)
    this._mesh = mesh
    mesh.castShadow = true
    mesh.receiveShadow = true
    this._addBoxes()
  }

  get objects() {
    return [this._mesh, ...this._boxMeshes]
  }

  _addBoxes = () => {
    // Add boxes
    const world = this._world
    const material = new THREE.MeshLambertMaterial({ color: '#222222' });
    var halfExtents = new CANNON.Vec3(1, 1, 1);
    var boxShape = new CANNON.Box(halfExtents);
    var boxGeometry = new THREE.BoxGeometry(halfExtents.x * 2, halfExtents.y * 2, halfExtents.z * 2);
    for (var i = 0; i < 7; i++) {
      var x = (Math.random() - 0.5) * 20;
      var y = 1 + (Math.random() - 0.5) * 1;
      var z = (Math.random() - 0.5) * 20;
      var boxBody = new CANNON.Body({ mass: 5 });
      boxBody.addShape(boxShape);
      var boxMesh = new THREE.Mesh(boxGeometry, material);
      world.addBody(boxBody);
      boxBody.position.set(x, y, z);
      boxMesh.position.set(x, y, z);
      boxMesh.castShadow = true;
      boxMesh.receiveShadow = true;
      this._boxes.push(boxBody);
      this._boxMeshes.push(boxMesh);
    }
  }

  next = () => {
    // Update box positions
    const boxes = this._boxes
    const boxMeshes = this._boxMeshes
    for (var i = 0; i < boxes.length; i++) {
      boxMeshes[i].position.copy(boxes[i].position);
      boxMeshes[i].quaternion.copy(boxes[i].quaternion);
    }
  }
}

export default Map
